const path = require('path');
const gulp = require('gulp');
const combiner = require('stream-combiner2');//将一系列流转换为单个流，用于监听流错误
const uglify = require('gulp-uglify');//压缩js
const webpackStream = require('webpack-stream');
const webpack = require('webpack');
const named = require('vinyl-named');
const del = require('del');
const watchPath = require('gulp-watch-path');
const replace = require('gulp-replace');
const inject = require('gulp-inject');//向html注入js和css

const connect = require('gulp-connect');//代理服务及热更新
const rev = require('gulp-rev');//项目部署缓存解决方案，对文件名加MD5后缀
const base64 = require('gulp-base64');
const runSequence = require('run-sequence');//按指定的顺序运行gulp任务
const postcss = require('gulp-postcss');
const autoprefixer = require('autoprefixer');//为CSS补全浏览器前缀
const precss = require('precss'); //提供像scss一样的语法
const cssnano = require('cssnano');  //更好用的css压缩!
const sass = require('gulp-sass');
const sourcemaps = require('gulp-sourcemaps');
const revCollector = require('gulp-rev-collector');//从manifests中获取静态资源版本数据,并且替换html中的链接，路径替换
// const webpackConfig = process.env.NODE_ENV === 'dev'? require('./webpack.config.dev') : require('./webpack.config.prod');
const webpackConfig = require('./webpack.config');

var BUILD = "DEV";


const processes = [
    autoprefixer({browsers: ['last 2 version', 'safari 5', 'opera 12.1', 'ios 6', 'android 4', '> 10%']}),//兼容浏览器
    precss,// background: color($blue blackness(20%));  precss为了用这样的语法
    cssnano//压缩css
];

const src = {
    css: './src/css/**/*.css',
    // fonts: './src/fonts/**/*.{eot,svg,ttf,woff}',
    fonts: './src/fonts/**/*',
    plugins: './src/plugins/**/*',
    images: './src/images/**/*.{png,jpg,jpeg,ico}',
    js: './src/js/**/*.js',
    mock: './src/mock/**/*.js',
    sass: './src/sass/**/*.scss',
    components: './src/components/**/*.{vue,jsx}',
    views: './src/views/**/*.html'
};
const dist = {
    css: './public/css/',
    fonts: './public/fonts/',
    plugins: './public/plugins/',
    images: './public/images/',
    js: './public/js/',
    sass: './public/sass/',
    views: './public/views/'
};
// dev启动
// 1.编译移动页面到public          OK
// 2.编译scss 输出到public         OK
// 3.编译js文件 输出public         OK
// 4.编译组件                      OK
// 5.输出图片和字体文件             OK
// 6.监听所有类型文件执行不同task    OK

// publish
// 编译 压缩 css
// 编译 压缩 js
// 移动 图片和字体

gulp.task('reload', function () {
    // debugger;
    webpackConfig.plugins.push(new webpack.DefinePlugin({
        'process.env': {
            NODE_ENV: JSON.stringify(process.env.NODE_ENV) ||  '"dev"'
        }
    }));
    runSequence('clean', 'js', 'sass', 'views:inject', 'images', 'fonts', 'plugins', 'watch', function () {
        connect.server({
            // name: '视频云平台',
            root: 'public',
            port: 3000,
            livereload: true
        });
    });

});

gulp.task('publish', function () {
    BUILD = 'PRODUCTION';

    webpackConfig.plugins.push(
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: JSON.stringify(process.env.NODE_ENV) || '"production"'
            }
        })
    );
    // console.log(process.env.NODE_ENV)
    runSequence('clean', 'plugins', 'sass', 'js:compile', 'views:inject', 'css:publish', 'chunk:publish', 'js:publish', 'views:publish', 'images', 'fonts', function() {
        del(['./src/tmp'])
    });
});

gulp.task('clean', function () {
    return del([
        'public/**/*', 'src/css/*'
    ]);
});

gulp.task('js', function () {
    cp('./src/js/lib/*.js','./public/js/lib');
    return compileJS(['./src/js/**/*.js','!./src/js/lib/*.js']);
});

gulp.task('views', function () {
    return gulp.src(src.views)
        .pipe(gulp.dest(dist.views))
        .pipe(connect.reload());
});

gulp.task('sass', function () {
    return gulp.src(src.sass)
        .pipe(sourcemaps.init())
        .pipe(sass().on('error', sass.logError))
        .pipe(sourcemaps.write('./maps'))
        .pipe(gulp.dest('./src/css'))
        .pipe(gulp.dest(dist.css))
        .pipe(connect.reload());
});

gulp.task('images', function () {
    return gulp.src([src.images, './src/tmp/images/*'])
        .pipe(gulp.dest(dist.images))
        .pipe(connect.reload());
});

gulp.task('fonts', function () {
    return gulp.src([src.fonts, './src/tmp/fonts/*'])
        .pipe(gulp.dest(dist.fonts))
        .pipe(connect.reload());
});

gulp.task('plugins', function () {
    return gulp.src(src.plugins)
        .pipe(gulp.dest(dist.plugins))
        .pipe(connect.reload());
});

gulp.task('js:compile', function () {
    cp('./src/js/lib/*.js','./public/js/lib');
    return compileJS(['./src/js/**/*.js','!./src/js/lib/*.js'],'./src/tmp');
    // return compileJS('./src/js/**/*.js','./src/tmp');
    // return compileJS('./src/js/**/*.js');
});

gulp.task('js:publish', function () {
    // return gulp.src('./public/js/**/*.js')
    //     .pipe(uglify({
    //         output:{max_line_len: 1000000}
    //     }))
    //     .pipe(rev())
    //     .pipe(gulp.dest(dist.js))
    //     .pipe(rev.manifest())
    //     .pipe(gulp.dest(dist.js))

    var combined = combiner.obj([
        gulp.src(['./src/tmp/js/**/*.js','!./src/tmp/js/**/chunk.*.js']),
        uglify(),
        rev(), //设置哈希值
        gulp.dest(dist.js),
        rev.manifest(), //设置哈希值json
        gulp.dest(dist.js)
    ]);

    // 任何在上面的 stream 中发生的错误，都不会抛出，
    // 而是会被监听器捕获
    combined.on('error', console.error.bind(console));

    return combined;

});

gulp.task('chunk:publish', function () { //懒加载块不能加哈希值
    // return gulp.src('./src/tmp/js/**/chunk.*.js')
    //     .pipe(uglify())
    //     .pipe(gulp.dest(dist.js));

    var combined = combiner.obj([
        gulp.src('./src/tmp/js/**/chunk.*.js'),
        uglify(),
        gulp.dest(dist.js)
    ]);

    // 任何在上面的 stream 中发生的错误，都不会抛出，
    // 而是会被监听器捕获
    combined.on('error', console.error.bind(console));

    return combined;
});

gulp.task('views:publish', function () {
    return gulp.src(['./public/**/*.json', './public/views/**/*.html'])
        .pipe(revCollector({
            replaceReved: true
        }))
        // .pipe(replace('../../', ''+ CDN +'/')) // 替换html页面静态资源地址
        // .pipe(replace('../', ''+ CDN +'/')) // 替换html页面静态资源地址
        .pipe(gulp.dest(dist.views));
});

gulp.task('css:publish', function () {

    del('public/css/*');

    return gulp.src([src.css, './src/tmp/css/**/*.css'])
        .pipe(base64({
            extensions: ['png', /\.jpg#datauri$/i],
            maxImageSize: 10 * 1024 // bytes,
        }))
        .pipe(postcss(processes))
        .pipe(rev()) //设置哈希值
        .pipe(gulp.dest(dist.css))
        .pipe(rev.manifest()) //设置哈希值json
        .pipe(gulp.dest(dist.css))

});

gulp.task('watch', function () {
    gulp.watch([src.views], ['views:inject']);
    gulp.watch([src.sass], ['sass']);
    gulp.watch([src.plugins], ['plugins']);
    gulp.watch([src.images], ['images']);
    gulp.watch([src.fonts], ['fonts']);
    gulp.watch([src.js], function (event) {
        let paths = watchPath(event, src.js, './public/js/');
        let sp = paths.srcPath.indexOf('\\') > -1 ? '\\' : '/';

        if(paths.srcPath.split(sp).length === 3) { // 共有库情况,要编译所有js
            compileJS(['./src/js/**/*.js','!./src/js/lib/*.js']);
        } else if(/lib/.test(paths.srcPath)){//修改静态资源
            // console.log(/lib/.test(paths.srcPath))
            cp(paths.srcPath,'./public/js/lib');
        }else { // 否则 只编译变动js
            compileJS(paths.srcPath);
        }
    });
    gulp.watch([src.mock], function (event) {
        let path = watchPath(event, src.mock, './public/js/').srcPath;
        path = path.replace('mock','js').replace('Mock','')

        compileJS(path);
    });
    gulp.watch([src.components], function (event) {
        let sp = event.path.indexOf('\\') > -1 ? '\\' : '/';
        let business = event.path.split(sp).slice(-2);
        let jsFile   = business[1].split('-')[0];
        let path;
        // console.log(business)
        if (business[0] === 'common') {
            path = ['./src/js/**/*.js','!./src/js/lib/*.js'];
        } else if (business[0] === jsFile) {
            path = './src/js/'+ business[0] +'/*.js';
        } else {
            path = './src/js/' + business[0] + '/' + jsFile + '.js';
        }
        compileJS(path);
    })
});

gulp.task('views:inject', function () {

    var reference = ['./src/fonts/font-awesome/css/font-awesome.min.css', './src/fonts/iconfont/iconfont.css'];
    var sources = ['./public/css/*.css', './public/js/common.js'];
    if(BUILD === 'PRODUCTION'){
        sources = ['./src/tmp/css/*.css', './src/tmp/js/common.js'];
    }

    return gulp.src(src.views)
        .pipe(inject(gulp.src(reference, {read: false}), {name: 'reference', relative: true, removeTags:true}))
        .pipe(inject(gulp.src(sources, {read: false}), {
            ignorePath:['public','src/tmp'],
            addRootSlash:false,
            removeTags:true,
            transform: function (filepath, file, i, length, targetFile) {
                // console.log(filepath, targetFile.history[0])
                let isCommon = /common/.test(filepath)
                let isJs = /.js/.test(filepath)
                let prePath = /index.html/.test(targetFile.history[0]) ? '../' : '../../'

                if(isCommon){
                    if(isJs){
                        return '<script src="' + prePath +filepath + '"></script>'
                    }
                    return '<link rel="stylesheet" href="' + prePath +filepath + '">'
                } else{
                    let sourceName = filepath.split('/').reverse()[0].replace('.css', '')
                    let targetName  = targetFile.history[0].split('\\views\\')[1].replace('.html', '').replace('\\', '-')

                    if(sourceName == targetName){
                        return '<link rel="stylesheet" href="' + prePath +filepath + '">'
                    }
                }
                // return '  "' + filepath + '"' + (i + 1 < length ? ',' : '');
            }
        }))
        .pipe(gulp.dest('./public/views'))
        .pipe(connect.reload());

});

function compileJS(path,dest) {
    dest = dest || './public';
    webpackConfig.output.publicPath = BUILD === 'PRODUCTION' ? '../../' : '/';

    return gulp.src(path)
        .pipe(named(function (file) {
            let path = JSON.parse(JSON.stringify(file)).history[0];
            let sp = path.indexOf('\\') > -1 ? '\\js\\' : '/js/';
            let target = path.split(sp)[1];
            // console.log(target.substring(0,target.length - 3))
            return target.substring(0,target.length - 3);
        }))
        .pipe(webpackStream(webpackConfig))
        .on('error',function(err) {
            this.end()
        })
        .pipe(gulp.dest(dest))
        .pipe(connect.reload());

}

function cp(from,to) {
    gulp.src(from)
        .pipe(gulp.dest(to));
}